LIBRARY IEEE; 
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE WORK.ic_1;
USE WORK.ic_2;
USE WORK.ic_3;
USE WORK.ic_4;
USE WORK.ic_5;
USE WORK.ic_6;
USE WORK.ic_7;
USE WORK.ic_8;
USE WORK.ic_9;

--Simulador de CIs

ENTITY tester IS

    PORT(clock, reset: IN STD_LOGIC := '0';
        l_pin: IN STD_LOGIC_VECTOR(7 DOWNTO 1);
        r_pin: IN STD_LOGIC_VECTOR(7 DOWNTO 1);
        works: OUT STD_LOGIC := '1';
        ic: OUT STD_LOGIC_VECTOR(11 DOWNTO 0):= (OTHERS => '0'));

END tester;

ARCHITECTURE logic OF tester IS

COMPONENT ic_1

    PORT(pin1, pin2, pin4, pin5, pin9, pin10, pin12, pin13: IN STD_LOGIC; 
        pin3, pin6, pin8, pin11: OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_2

    PORT(pin1, pin3, pin5, pin9, pin11, pin13: IN STD_LOGIC; 
        pin2, pin4, pin6, pin8, pin10, pin12: OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_3 IS

    PORT(pin1, pin2, pin3, pin4, pin5, pin9, pin10, pin11, pin13: IN STD_LOGIC; 
        pin6, pin8, pin12: OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_4 IS

    PORT(pin1, pin2, pin4, pin5, pin9, pin10, pin12, pin13: IN STD_LOGIC; 
        pin6, pin8: OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_5 IS

    PORT(clear, pin1, pin4, pin8, pin9, pin10, pin11, pin12, pin13 :IN STD_LOGIC; 
        pin2, pin3, pin5, pin6:OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_6 IS

    PORT(clear, pin1, pin2, pin3, pin4, pin5, pin6, pin7: IN STD_LOGIC; 
        pin9, pin10, pin11, pin12, pin13, pin14, pin15: OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_7 IS

    PORT(clear, pin1, pin2, pin3, pin4, pin5, pin6, pin10, pin11, pin12, pin13, pin14, pin15 : IN STD_LOGIC; 
        pin7, pin9: OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_8 IS

    PORT(clear, pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin9, pin10: IN STD_LOGIC; 
        pin11, pin12, pin13, pin14, pin15: OUT STD_LOGIC);

END COMPONENT;

COMPONENT ic_9 IS

    PORT(clear, pin1, pin2, pin11, pin12, pin13, pin14, pin7, pin9, pin10, pin15: IN STD_LOGIC := '0'; 
        pin3, pin4, pin5, pin6: OUT STD_LOGIC := '0');

END COMPONENT;

SIGNAL and1, and2, and3, and4: STD_LOGIC := '0';
SIGNAL or1, or2, or3, or4: STD_LOGIC := '0';
SIGNAL nand1, nand2, nand3, nand4: STD_LOGIC := '0';
SIGNAL nand31, nand32, nand33: STD_LOGIC := '0';
SIGNAL nand41, nand42: STD_LOGIC := '0';
SIGNAL xor1, xor2, xor3, xor4: STD_LOGIC := '0';
SIGNAL not1, not2, not3, not4, not5, not6: STD_LOGIC := '0';
SIGNAL jkff1, jkff2, jkffn1, jkffn2: STD_LOGIC := '0';
SIGNAL bcda, bcdb, bcdc, bcdd, bcde, bcdf, bcdg: STD_LOGIC := '0';
SIGNAL mux1, mux2: STD_LOGIC := '0';
SIGNAL counter1, counter2, counter3, counter4, counterRCO: STD_LOGIC := '0';
SIGNAL regd1, regd2, regd3, regd4: STD_LOGIC := '0';

SIGNAL and_reg, or_reg, nand_reg, not_reg, xor_reg, nand3_reg, nand4_reg, jkff_reg: STD_LOGIC := '1';
SIGNAL bcd_reg, mux_reg, counter_reg, register_reg: STD_LOGIC := '1';

--denotando qual arquitetura vamos usar para cada componente
FOR nand_test: ic_1 USE ENTITY WORK.ic_1(nand_ic); --7400
FOR not_test: ic_2 USE ENTITY WORK.ic_2(not_ic); --7404
FOR and_test: ic_1 USE ENTITY WORK.ic_1(and_ic); --7408
FOR or_test: ic_1 USE ENTITY WORK.ic_1(or_ic); --7432
FOR xor_test: ic_1 USE ENTITY WORK.ic_1(xor_ic); --7486
FOR nand3_test: ic_3 USE ENTITY WORK.ic_3(nand3_ic); --7410
FOR nand4_test: ic_4 USE ENTITY WORK.ic_4(nand4_ic); --7420
FOR jkffa_test: ic_5 USE ENTITY WORK.ic_5(jkffa_ic); --74107
FOR bcd_test: ic_6 USE ENTITY WORK.ic_6(bcdto7seg_ic); --74148
FOR mux2_test: ic_7 USE ENTITY WORK.ic_7(mux2_ic); --74153
FOR counter_test: ic_8 USE ENTITY WORK.ic_8(bit4_counter_ic); --74163
FOR register_test: ic_9 USE ENTITY WORK.ic_9(bit4_register_ic); --74173

BEGIN

    and_test: ic_1
    PORT MAP(pin1=>l_pin(1), pin2=>l_pin(2), pin3=>and1, pin4=>l_pin(4), pin5=>l_pin(5), pin6=>and2,
        pin8=>and3, pin9=>r_pin(5), pin10=>r_pin(4), pin11=>and4, pin12=>r_pin(2), pin13=>r_pin(1));

    or_test: ic_1
    PORT MAP(pin1=>l_pin(1), pin2=>l_pin(2), pin3=>or1, pin4=>l_pin(4), pin5=>l_pin(5), pin6=>or2,
        pin8=>or3, pin9=>r_pin(5), pin10=>r_pin(4), pin11=>or4, pin12=>r_pin(2), pin13=>r_pin(1));

    nand_test: ic_1
    PORT MAP(pin1=>l_pin(1), pin2=>l_pin(2), pin3=>nand1, pin4=>l_pin(4), pin5=>l_pin(5), pin6=>nand2,
        pin8=>nand3, pin9=>r_pin(5), pin10=>r_pin(4), pin11=>nand4, pin12=>r_pin(2), pin13=>r_pin(1));

    xor_test: ic_1
    PORT MAP(pin1=>l_pin(1), pin2=>l_pin(2), pin3=>xor1, pin4=>l_pin(4), pin5=>l_pin(5), pin6=>xor2,
        pin8=>xor3, pin9=>r_pin(5), pin10=>r_pin(4), pin11=>xor4, pin12=>r_pin(2), pin13=>r_pin(1));

    not_test: ic_2
    PORT MAP(pin1=>l_pin(1), pin2=>not1, pin3=>l_pin(3), pin4=>not2, pin5=>l_pin(5), pin6=>not3,
        pin8=>not4, pin9=>r_pin(5), pin10=>not5, pin11=>r_pin(3), pin12=>not6, pin13=>r_pin(1));

    nand3_test: ic_3
    PORT MAP(pin1=>l_pin(1), pin2=>l_pin(2), pin3=>l_pin(3), pin4=>l_pin(4), pin5=>l_pin(5), pin6=>nand32,
        pin8=>nand33, pin9=>r_pin(5), pin10=>r_pin(4), pin11=>r_pin(3), pin12=>nand31, pin13=>r_pin(1));

    nand4_test: ic_4
    PORT MAP(pin1=>l_pin(1), pin2=>l_pin(2), pin4=>l_pin(4), pin5=>l_pin(5), pin6=>nand41,
        pin8=>nand42, pin9=>r_pin(5), pin10=>r_pin(4), pin12=>r_pin(2), pin13=>r_pin(1));

    jkffa_test: ic_5
    PORT MAP(clear=>reset, pin1=>l_pin(1), pin2=>jkffn1, pin3=>jkff1, pin4=>l_pin(4), pin5=>jkff2, pin6=>jkffn2,
        pin8=>r_pin(6), pin9=>r_pin(5), pin10=>r_pin(4), pin11=>r_pin(3), pin12=>r_pin(2), pin13=>r_pin(1));
		  
    bcd_test: ic_6
    PORT MAP(clear=>reset, pin1=>l_pin(1), pin2=>l_pin(2), pin3=>l_pin(3), pin4=>l_pin(4), 
        pin5=>l_pin(5), pin6=>l_pin(6), pin7=>l_pin(7), pin9=>bcde, pin10=>bcdd, 
        pin11=>bcdc, pin12=>bcdb, pin13=>bcda, pin14=>bcdg, pin15=>bcdf);
		  
    mux2_test: ic_7
    PORT MAP(clear=>reset, pin1=>l_pin(1), pin2=>l_pin(2), pin3=>l_pin(3), pin4=>l_pin(4), 
        pin5=>l_pin(5), pin6=>l_pin(6), pin7=>mux1, pin9=>mux2, pin10=>r_pin(6), 
        pin11=>r_pin(5), pin12=>r_pin(4), pin13=>r_pin(3), pin14=>r_pin(2), pin15=>r_pin(1));
		  
    counter_test: ic_8
    PORT MAP(clear=>reset, pin1=>l_pin(1), pin2=>l_pin(2), pin3=>l_pin(3), pin4=>l_pin(4), 
        pin5=>l_pin(5), pin6=>l_pin(6), pin7=>l_pin(7), pin9=>r_pin(7), pin10=>r_pin(6), 
        pin11=>counter4, pin12=>counter3, pin13=>counter2, pin14=>counter1, pin15=>counterRCO);

    register_test: ic_9
    PORT MAP(clear=>reset, pin1=>l_pin(1), pin2=>l_pin(2), pin3=>regd1, pin4=>regd2, 
        pin5=>regd3, pin6=>regd4, pin7=>l_pin(7), pin9=>r_pin(7), pin10=>r_pin(6), 
        pin11=>r_pin(5), pin12=>r_pin(4), pin13=>r_pin(3), pin14=>r_pin(2), pin15=>r_pin(1));

    PROCESS(clock, l_pin, r_pin)
    BEGIN

        works <= and_reg OR or_reg OR nand_reg OR not_reg OR xor_reg OR 
                 nand3_reg OR nand4_reg OR jkff_reg OR bcd_reg OR
                 mux_reg OR counter_reg OR register_reg;

        ic(0) <= nand_reg;
        ic(1) <= and_reg;
        ic(2) <= or_reg;
        ic(3) <= xor_reg;
        ic(4) <= not_reg;
        ic(5) <= nand3_reg;
        ic(6) <= nand4_reg;
        ic(7) <= jkff_reg;
        ic(8) <= bcd_reg;
        ic(9) <= mux_reg;
        ic(10) <= counter_reg;
        ic(11) <= register_reg;

        IF(clock = '1' AND clock'event) THEN
           IF(reset = '1') THEN -- reset sincrono
                and_reg <= '1';
                or_reg <= '1';
                nand_reg <= '1';
                not_reg <= '1';
                xor_reg <= '1';
                nand3_reg <= '1';
                nand4_reg <= '1';
                jkff_reg <= '1';
                bcd_reg <= '1';
                mux_reg <= '1';
                counter_reg <= '1';
                register_reg <= '1';
            ELSE
                and_reg <= and_reg AND ((and1 XNOR l_pin(3)) AND (and2 XNOR l_pin(6)) AND 
                    (and3 XNOR r_pin(6)) AND (and4 XNOR r_pin(3)) AND 
                    (l_pin(7) XNOR '0') AND (r_pin(7) XNOR '0'));
                or_reg <= or_reg AND ((or1 XNOR l_pin(3)) AND (or2 XNOR l_pin(6)) AND 
                    (or3 XNOR r_pin(6)) AND (or4 XNOR r_pin(6)) AND
                    (l_pin(7) XNOR '0') AND (r_pin(7) XNOR '0'));
                nand_reg <= nand_reg AND ((nand1 XNOR r_pin(3)) AND (nand2 XNOR l_pin(6)) AND 
                    (nand3 XNOR r_pin(6)) AND (nand4 XNOR r_pin(3)) AND
                    (l_pin(7) XNOR '0') AND (r_pin(7) XNOR '0'));
                xor_reg <= xor_reg AND ((xor1 XNOR l_pin(3)) AND (xor2 XNOR l_pin(6)) AND 
                    (xor3 XNOR r_pin(6)) AND (xor4 XNOR r_pin(3)) AND
                    (l_pin(7) XNOR '0') AND (r_pin(7) XNOR '0'));
                not_reg <= not_reg AND ((not1 XNOR l_pin(2)) AND (not2 XNOR l_pin(4)) AND 
                    (not3 XNOR l_pin(6)) AND (not4 XNOR r_pin(6)) AND 
                    (not5 XNOR r_pin(4)) AND (not6 XNOR r_pin(2)) AND
                    (l_pin(7) XNOR '0') AND (r_pin(7) XNOR '0'));
                nand3_reg <= nand3_reg AND ((nand31 XNOR r_pin(2)) AND (nand32 XNOR l_pin(6)) AND
                    (nand33 XNOR r_pin(6)) AND (l_pin(7) XNOR '0') AND 
                    (r_pin(7) XNOR '0'));
                nand4_reg <= nand4_reg AND ((nand41 XNOR l_pin(6)) AND (nand42 XNOR r_pin(6)) AND 
                    (l_pin(3) XNOR '0') AND (r_pin(3) XNOR '0') AND 
                    (l_pin(7) XNOR '0') AND (r_pin(7) XNOR '0'));
                jkff_reg <= jkff_reg AND ((jkff1 XNOR l_pin(3)) AND (jkffn1 XNOR l_pin(2)) AND 
                    (jkff2 XNOR l_pin(5)) AND (jkffn2 XNOR l_pin(6)) AND
                    (l_pin(7) XNOR '0') AND (r_pin(7) XNOR '0'));
                bcd_reg <= bcd_reg AND ((r_pin(3) XNOR bcda) AND (r_pin(4) XNOR bcdb) AND
                    (r_pin(5) XNOR bcdc) AND (r_pin(6) XNOR bcdd) AND (r_pin(7) XNOR bcde) AND
                    (r_pin(1) XNOR bcdf) AND (r_pin(2) XNOR bcdg));
                mux_reg <= mux_reg AND ((l_pin(7) XNOR mux1) AND (r_pin(7) XNOR mux2));
                counter_reg <= counter_reg AND ((r_pin(2) XNOR counter1) AND (r_pin(3) XNOR counter2) AND
                    (r_pin(4) XNOR counter3) AND (r_pin(5) XNOR counter4) AND
                    (r_pin(1) XNOR counterRCO));
                IF(l_pin(1) = '1' OR l_pin(2) = '1')THEN
                    register_reg <= register_reg;
                ELSE
                    register_reg <= register_reg AND ((l_pin(3) XNOR regd1) AND (l_pin(4) XNOR regd2) AND
                        (l_pin(5) XNOR regd3) AND (l_pin(6) XNOR regd4));
                END IF;
            END IF;
        END IF;
    END PROCESS;

END logic;